﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using Microsoft.SolverFoundation.Services;

namespace Flux_Balance_Analysis
{
    /// <summary>
    /// Logica di interazione per ConstraintsManager.xaml
    /// </summary>
    public partial class ConstraintsManager : UserControl
    {
        public event EventHandler ConstraintChanged;

        public bool Readonly
        {
            get { return this._readonly; }
            set
            {
                this._readonly = value;
                if (value)
                {
                    grpbFilter.Visibility = System.Windows.Visibility.Collapsed;
                    cmdAddConstraint.Visibility = System.Windows.Visibility.Collapsed;
                    this.IsEnabled = false;
                }
                else
                {
                    grpbFilter.Visibility = System.Windows.Visibility.Visible;
                    cmdAddConstraint.Visibility = System.Windows.Visibility.Visible;
                    this.IsEnabled = true;
                }
            }
        }

        public string Filter
        {
            get { return txtFilter.Text; }
            set { txtFilter.Text = value; }
        }

        bool _readonly = false;
        List<ConstraintControl> deleted = new List<ConstraintControl>();

        public ConstraintsManager()
        {
            InitializeComponent();
        }

        public void CommitChange()
        {
            // rimuovo tutti i vincoli che ho eliminato
            foreach (var ctrl in deleted)
            {
                FBACore.RemoveConstraint(FBACore.Constraints.FirstOrDefault(c => c.Name == ctrl.ConstraintName));
            }

            // scorro tutti i vincoli della finstra
            IEnumerable<ConstraintControl> controls = spConstraints.Children.OfType<ConstraintControl>();
            foreach (var ctrl in controls)
            {
                // se è già presente nell'insieme, allora lo aggiorno
                Constraint constraint = FBACore.Constraints.FirstOrDefault(c => c.Name == ctrl.ConstraintName);
                if (constraint != null)
                {
                    FBACore.RemoveConstraint(constraint);
                }
                FBACore.AddConstraint(ctrl.ConstraintName, ctrl.ConstraintExpression, ctrl.ConstraintEnabled);
            }
        }

        void Clear()
        {
            // ottengo il pulsante
            Button cmd = spConstraints.Children.OfType<Button>().FirstOrDefault();

            // pulisco il pannello
            spConstraints.Children.Clear();

            // reinserisco il pulsante
            spConstraints.Children.Add(cmd);
        }

        void DoFilter()
        {
            Clear();
            // ottengo tutti i constraint
            IEnumerable<Constraint> constraints = FBACore.Constraints;

            // li filtro
            if (!string.IsNullOrWhiteSpace(txtFilter.Text))
            {
                constraints = constraints.Where(c => c.Expression.Contains(txtFilter.Text));
            }

            // li aggiungo al controllo
            foreach (var constraint in constraints)
            {
                AddConstraint(constraint);
            }
        }

        void AddConstraint(Constraint constraint)
        {
            ConstraintControl cControl = new ConstraintControl();
            if (constraint != null)
            {
                cControl.ConstraintName = constraint.Name;
                cControl.ConstraintExpression = constraint.Expression;
                cControl.ConstraintEnabled = constraint.Enabled;
            }
            else
            {
                cControl.ConstraintName = "_C" + FBACore.Constraints.Count();
            }

            if(cControl.ConstraintName[0] != '_')
                cControl.IsEnabled = false;

            cControl.DelectionRequired += new EventHandler(constraint_DelectionRequired);
            cControl.ConstraintChanged += cControl_ConstraintChanged;
            spConstraints.Children.Insert(spConstraints.Children.Count - 1, cControl);
        }

        void cControl_ConstraintChanged(object sender, EventArgs e)
        {
            if(ConstraintChanged != null)
                ConstraintChanged(sender, e);
        }

        private void cmdAddConstraint_Click(object sender, RoutedEventArgs e)
        {
            AddConstraint(null);
            if (ConstraintChanged != null)
                ConstraintChanged(null, null);
        }

        void constraint_DelectionRequired(object sender, EventArgs e)
        {
            spConstraints.Children.Remove(sender as ConstraintControl);
            deleted.Add(sender as ConstraintControl);
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            DoFilter();
        }

        private void txtFilter_TextChanged(object sender, TextChangedEventArgs e)
        {
            DoFilter();
        }
    }
}
